{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d44fcc7d-37bb-4ecd-997e-a71168e6b8bb",
   "metadata": {},
   "source": [
    "# Using QSVT for matrix inversion"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "824bed94-9040-4bf4-87dc-a0f84dc155dd",
   "metadata": {},
   "source": [
    "In this notebook, we will use the Quantum Singular Value Transformation (QSVT) algorithm to solve the problem of matrix inversion.\n",
    "The demo is based on the paper [Grand unification of quantum algorithms](#grand)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42f4d5f6-3527-4421-93ab-91343957969e",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Problem Encoding"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df475c3d-8911-47c0-bae2-4ac812858238",
   "metadata": {},
   "source": [
    "We start by defining a specific problem. We can take matrix that is not symmetric, in comparison to the HHL algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1853e4a5-d9d0-4678-999f-1537e00e88ad",
   "metadata": {
    "tags": []
   },
   "source": [
    "We will encode $A$ in a larger Unitary matrix. For simplicity, we will just sample a random unitary U_a, and take it's first block as $A$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "11ebea38-e9f7-4faa-a282-054520125a11",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:03.904535Z",
     "start_time": "2024-04-10T09:50:03.779624Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:08.945384Z",
     "iopub.status.busy": "2024-05-07T14:31:08.944884Z",
     "iopub.status.idle": "2024-05-07T14:31:09.100310Z",
     "shell.execute_reply": "2024-05-07T14:31:09.099723Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-0.05338002 -0.36103662 -0.54016489 -0.39026125]\n",
      " [-0.33304121  0.10648228  0.37346704 -0.33977916]\n",
      " [ 0.4167817  -0.75180519  0.17593867  0.20944773]\n",
      " [ 0.26891079 -0.05333795 -0.32668787 -0.33602829]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import scipy\n",
    "\n",
    "# the size of the unitary which block encodes A\n",
    "REG_SIZE = 3\n",
    "\n",
    "\n",
    "def get_random_unitary(num_qubits, seed=4):\n",
    "    np.random.seed(seed)\n",
    "    X = np.random.rand(2**num_qubits, 2**num_qubits)\n",
    "    U, s, V = np.linalg.svd(X)\n",
    "    return U @ V.T\n",
    "\n",
    "\n",
    "U_a = get_random_unitary(REG_SIZE)\n",
    "\n",
    "A_dim = int(U_a.shape[0] / 2)\n",
    "A = U_a[:A_dim, :A_dim]\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e988a4aa-158a-4873-a021-e2968e300dd6",
   "metadata": {},
   "source": [
    "Make sure A's singular values are smaller than 1:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f847189d-0bb3-4d51-9037-1d1af4fd4be2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:03.905078Z",
     "start_time": "2024-04-10T09:50:03.835377Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:09.104742Z",
     "iopub.status.busy": "2024-05-07T14:31:09.103526Z",
     "iopub.status.idle": "2024-05-07T14:31:09.108646Z",
     "shell.execute_reply": "2024-05-07T14:31:09.108042Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "assert not (np.linalg.svd(A)[1] > 1).sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "94590dad-6107-4ba7-aadd-21381e91ca0d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:03.905238Z",
     "start_time": "2024-04-10T09:50:03.838990Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:09.112635Z",
     "iopub.status.busy": "2024-05-07T14:31:09.111593Z",
     "iopub.status.idle": "2024-05-07T14:31:09.117801Z",
     "shell.execute_reply": "2024-05-07T14:31:09.117220Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.         0.26726124 0.53452248 0.80178373]\n"
     ]
    }
   ],
   "source": [
    "b = np.arange(A_dim)\n",
    "b = b / np.linalg.norm(b)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a996b498-270f-4f0e-8d68-2aaa388d1dd5",
   "metadata": {},
   "source": [
    "Verify $U_{a}$ is indeed unitary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "26a5a9f1-de34-4f4b-bb6b-3fda8aacbadc",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:03.905328Z",
     "start_time": "2024-04-10T09:50:03.842517Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:09.121931Z",
     "iopub.status.busy": "2024-05-07T14:31:09.120858Z",
     "iopub.status.idle": "2024-05-07T14:31:09.126053Z",
     "shell.execute_reply": "2024-05-07T14:31:09.125456Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "assert np.allclose(U_a @ U_a.T, np.eye(U_a.shape[0]), rtol=1e-5, atol=1e-6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11a86ae0-e2d9-4149-a372-c704f9e6c0fa",
   "metadata": {},
   "source": [
    "Calculate the condition number $\\kappa=max(\\frac{1}{\\sigma_i})$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "51915b86-9616-4531-bc8e-5fb6ea41910c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:03.905430Z",
     "start_time": "2024-04-10T09:50:03.846368Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:09.130537Z",
     "iopub.status.busy": "2024-05-07T14:31:09.129397Z",
     "iopub.status.idle": "2024-05-07T14:31:09.135618Z",
     "shell.execute_reply": "2024-05-07T14:31:09.135048Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.459862838470874\n"
     ]
    }
   ],
   "source": [
    "kappa = max(1 / np.linalg.svd(A)[1])\n",
    "print(kappa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "46de84db-fc65-4ad0-b9c0-cdba0681ab05",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:03.905596Z",
     "start_time": "2024-04-10T09:50:03.850200Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:09.140107Z",
     "iopub.status.busy": "2024-05-07T14:31:09.139063Z",
     "iopub.status.idle": "2024-05-07T14:31:09.149061Z",
     "shell.execute_reply": "2024-05-07T14:31:09.148526Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.99132079, 0.84978294, 0.52403662, 0.2890288 ])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.svd(A)[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d95795a-c45b-4533-b7e0-2b410b824717",
   "metadata": {},
   "source": [
    "## Now to the quantum part!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7a50491-4447-4e42-9330-1416e14ff583",
   "metadata": {
    "tags": []
   },
   "source": [
    "### Defining the QSVT circuit for the problem"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8be8918a-b752-480e-ae63-9fe39151d23a",
   "metadata": {},
   "source": [
    "We start with the general qsvt framework definition. It accepts a unitary which block-encode a matrix together with projector-controlled-cnot functions which identify the block in which the matrix is encoded.\n",
    "\n",
    "It applies the `qsvt_step` multiple times, iterating over the rotation angles provided which encode the polynomial transformation.\n",
    "Notice - The last step is quite tricky and depend on the specific transformation we wish to perform. Here the code is suitable for the matrix-inversion case. Also - we wrap the auxilliary qubit with $H$ gates."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "04323c28-79a8-44b5-9531-782e36853511",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.481927Z",
     "start_time": "2024-04-10T09:50:03.862462Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:09.153066Z",
     "iopub.status.busy": "2024-05-07T14:31:09.152437Z",
     "iopub.status.idle": "2024-05-07T14:31:11.744566Z",
     "shell.execute_reply": "2024-05-07T14:31:11.743643Z"
    },
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "from classiq.qmod import (\n",
    "    CX,\n",
    "    IDENTITY,\n",
    "    RZ,\n",
    "    CArray,\n",
    "    CInt,\n",
    "    CReal,\n",
    "    H,\n",
    "    Output,\n",
    "    QArray,\n",
    "    QBit,\n",
    "    QCallable,\n",
    "    X,\n",
    "    allocate,\n",
    "    bind,\n",
    "    if_,\n",
    "    invert,\n",
    "    prepare_amplitudes,\n",
    "    qfunc,\n",
    "    repeat,\n",
    "    unitary,\n",
    ")\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def my_projector_controlled_phase(\n",
    "    phase: CReal,\n",
    "    proj_cnot: QCallable[QArray[QBit], QBit],\n",
    "    qbv_reg: QArray[QBit],\n",
    "    qbv_aux: QBit,\n",
    ") -> None:\n",
    "    proj_cnot(qbv_reg, qbv_aux)\n",
    "    RZ(phase, qbv_aux)\n",
    "    proj_cnot(qbv_reg, qbv_aux)\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def my_qsvt_step(\n",
    "    phase_seq: CArray[CReal],\n",
    "    index: CInt,\n",
    "    proj_cnot_1: QCallable[QArray[QBit], QBit],\n",
    "    proj_cnot_2: QCallable[QArray[QBit], QBit],\n",
    "    u: QCallable[QArray[QBit]],\n",
    "    qbv: QArray[QBit],\n",
    "):\n",
    "    qbv_reg = QArray(\"qbv_reg\")\n",
    "    qbv_aux = QArray(\"qbv_aux\", length=1)\n",
    "\n",
    "    bind(qbv, [qbv_reg, qbv_aux])\n",
    "\n",
    "    my_projector_controlled_phase(phase_seq[2 * index], proj_cnot_1, qbv_reg, qbv_aux)\n",
    "    u(qbv_reg)\n",
    "    my_projector_controlled_phase(\n",
    "        phase_seq[2 * index + 1],\n",
    "        proj_cnot_2,\n",
    "        qbv_reg,\n",
    "        qbv_aux,\n",
    "    )\n",
    "\n",
    "    if_(\n",
    "        condition=2 * index + 2 == phase_seq.len,\n",
    "        then=lambda: IDENTITY(qbv_reg),\n",
    "        else_=lambda: invert(lambda: u(qbv_reg)),\n",
    "    )\n",
    "\n",
    "    bind([qbv_reg, qbv_aux], qbv)\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def my_qsvt(\n",
    "    phase_seq: CArray[CReal],\n",
    "    proj_cnot_1: QCallable[QArray[QBit], QBit],\n",
    "    proj_cnot_2: QCallable[QArray[QBit], QBit],\n",
    "    u: QCallable[QArray[QBit]],\n",
    "    qbv_reg: QArray[QBit],\n",
    "    qbv_aux: QBit,\n",
    ") -> None:\n",
    "    H(qbv_aux)\n",
    "\n",
    "    qbv = QArray(\"qbv\")\n",
    "    bind([qbv_reg, qbv_aux], qbv)\n",
    "    repeat(\n",
    "        count=phase_seq.len / 2,\n",
    "        iteration=lambda index: my_qsvt_step(\n",
    "            phase_seq, index, proj_cnot_1, proj_cnot_2, u, qbv\n",
    "        ),\n",
    "    )\n",
    "\n",
    "    bind(qbv, [qbv_reg, qbv_aux])\n",
    "    H(qbv_aux)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "43b71428-1835-4637-a352-b9658f0ca240",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "### Matrix inversion logic\n",
    "\n",
    "Here define the specific use case of the matrix inversion. In this case, both projectors are the same, and expect the block encoded matrix to apply on the states where the first qubit value is $|0\\rangle$, hence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "9b2ae389-fad7-4ad6-b7c8-58a1168f053a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.485115Z",
     "start_time": "2024-04-10T09:50:05.482393Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:11.765498Z",
     "iopub.status.busy": "2024-05-07T14:31:11.764712Z",
     "iopub.status.idle": "2024-05-07T14:31:11.772471Z",
     "shell.execute_reply": "2024-05-07T14:31:11.771777Z"
    }
   },
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def my_qsvt_inversion(\n",
    "    phase_seq: CArray[CReal],\n",
    "    u: QCallable[QArray[QBit]],\n",
    "    qbv_reg: QArray[QBit],\n",
    "    qbv_aux: Output[QBit],\n",
    ") -> None:\n",
    "    allocate(1, qbv_aux)\n",
    "\n",
    "    def _projector_cnot(qbv_state: QArray[QBit], qbv_aux: QBit):\n",
    "        X(qbv_state[qbv_state.len - 1])\n",
    "        CX(qbv_state[qbv_state.len - 1], qbv_aux)\n",
    "        X(qbv_state[qbv_state.len - 1])\n",
    "\n",
    "    my_qsvt(\n",
    "        phase_seq,\n",
    "        lambda arg0, arg1: _projector_cnot(arg0, arg1),\n",
    "        lambda arg0, arg1: _projector_cnot(arg0, arg1),\n",
    "        u,\n",
    "        qbv_reg,\n",
    "        qbv_aux,\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b9160aa-c9b0-46ff-a29f-214a344610b8",
   "metadata": {},
   "source": [
    "### Get the phase sequence for the inverse function"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70e43073-d7c1-438c-9bef-1c4c6fa4f363",
   "metadata": {
    "tags": []
   },
   "source": [
    "Get directly the coef of the sign function, based on the erfc approximation, using the `pyqsp` package:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "37ecca28-278e-4b83-987e-25d9d18492a0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.519078Z",
     "start_time": "2024-04-10T09:50:05.485726Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:11.786637Z",
     "iopub.status.busy": "2024-05-07T14:31:11.785398Z",
     "iopub.status.idle": "2024-05-07T14:31:11.834811Z",
     "shell.execute_reply": "2024-05-07T14:31:11.834120Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b=50, j0=20\n",
      "[PolyOneOverX] minimum [-4.54115308] is at [-0.15883407]: normalizing\n",
      "[PolyOneOverX] bounding to 0.5\n",
      "[pyqsp.PolyOneOverX] pcoefs=[ 0.00000000e+00  5.50501781e+00  0.00000000e+00 -1.34815163e+02\n",
      "  0.00000000e+00  2.15191868e+03  0.00000000e+00 -2.50709632e+04\n",
      "  0.00000000e+00  2.25502975e+05  0.00000000e+00 -1.61156021e+06\n",
      "  0.00000000e+00  9.27860774e+06  0.00000000e+00 -4.33007019e+07\n",
      "  0.00000000e+00  1.64161062e+08  0.00000000e+00 -5.05820849e+08\n",
      "  0.00000000e+00  1.26571548e+09  0.00000000e+00 -2.56671992e+09\n",
      "  0.00000000e+00  4.20178645e+09  0.00000000e+00 -5.51711201e+09\n",
      "  0.00000000e+00  5.75258027e+09  0.00000000e+00 -4.69115938e+09\n",
      "  0.00000000e+00  2.92363543e+09  0.00000000e+00 -1.34306985e+09\n",
      "  0.00000000e+00  4.28212620e+08  0.00000000e+00 -8.45647522e+07\n",
      "  0.00000000e+00  7.78663704e+06]\n"
     ]
    }
   ],
   "source": [
    "import pyqsp\n",
    "\n",
    "pg = pyqsp.poly.PolyOneOverX()\n",
    "pcoefs = pg.generate(epsilon=0.05, kappa=kappa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6ac475fa-cc25-402a-8474-2f931f5ff279",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.643313Z",
     "start_time": "2024-04-10T09:50:05.513954Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:11.839318Z",
     "iopub.status.busy": "2024-05-07T14:31:11.838113Z",
     "iopub.status.idle": "2024-05-07T14:31:12.271038Z",
     "shell.execute_reply": "2024-05-07T14:31:12.270312Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from pyqsp.angle_sequence import Polynomial, QuantumSignalProcessingPhases\n",
    "\n",
    "poly = Polynomial(pcoefs)\n",
    "\n",
    "# choosing 'z' this basis since P(1)=1 and won't to avoid the QSP basis change. Anyway, we are not measuring directly this qubit.\n",
    "ang_seq = QuantumSignalProcessingPhases(\n",
    "    poly, signal_operator=\"Wx\", method=\"laurent\", measurement=\"x\"\n",
    ")\n",
    "pyqsp.response.PlotQSPResponse(ang_seq, signal_operator=\"Wx\", measurement=\"x\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e30167a-ff5a-49f5-bf56-0e505c533a95",
   "metadata": {},
   "source": [
    "#### Adjusting phase conventions"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01809547-4727-4dce-89aa-41a15df3e33a",
   "metadata": {},
   "source": [
    "There conventions by which the `pyqsp` package calculates the the phases are different from the phases we need for this qsvt circuit. The following block takes care for them."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c515575-100b-400e-8d24-9bb8e4ab70e2",
   "metadata": {},
   "source": [
    "As $R(a)=-i*e^{i\\frac{\\pi}{4}Z}W(a)e^{i\\frac{\\pi}{4}Z}$ and we have odd number of rotations, we get an i phase to our polynomial, so we get $Im(P(a))$ instead of the real part. So we will get the result in the $|1\\rangle$ state in the ancilla. However, we can fix it by adding $\\pi/2$ phase to the last or first rotation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "faf61f54-ad97-4c86-bcff-3605c515f7d7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.645400Z",
     "start_time": "2024-04-10T09:50:05.643011Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:12.275729Z",
     "iopub.status.busy": "2024-05-07T14:31:12.274528Z",
     "iopub.status.idle": "2024-05-07T14:31:12.280910Z",
     "shell.execute_reply": "2024-05-07T14:31:12.280123Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# change the R(x) to W(x), as the phases are in the W(x) conventions\n",
    "phases = np.array(ang_seq)\n",
    "phases = phases - np.pi / 2\n",
    "phases[0] = phases[0] + np.pi / 4\n",
    "phases[-1] = phases[-1] + np.pi / 4 + np.pi / 2\n",
    "\n",
    "# verify conventions. minus is due to exp(-i*phi*z) in qsvt in comparison to qsp\n",
    "phases = -2 * phases"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74588c18-8231-4c0d-8bce-6a70b31edca3",
   "metadata": {},
   "source": [
    "### Using the inversion function to solve linear system - `main` function\n",
    "\n",
    "The following block defines the `main` function. This is the entry point for the quantum algorithm, which brings all previous parts together.\n",
    "\n",
    "Specifically, we will use the function `prepare_amplitudes` for loading the vector $b$ into the quantum state.\n",
    "\n",
    "Then apply the 'qsvt_inversion`. We use the to the dagger of the unitary $U$ which block encodes $A$, because, using the SVD decomposition:\n",
    "$$\n",
    "\\begin{align}\n",
    "A &=W\\Sigma V^\\dagger\\\\\n",
    "A^\\dagger &=V^\\dagger \\Sigma W\\\\\n",
    "A^{-1} &= V^\\dagger \\Sigma^{-1}W\\\\\n",
    "\\end{align}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "939339d7-260d-4403-8361-0fcb168f5b0d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.649261Z",
     "start_time": "2024-04-10T09:50:05.646131Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:12.284874Z",
     "iopub.status.busy": "2024-05-07T14:31:12.283905Z",
     "iopub.status.idle": "2024-05-07T14:31:12.290316Z",
     "shell.execute_reply": "2024-05-07T14:31:12.289746Z"
    }
   },
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def main(\n",
    "    qbv_state: Output[QArray[QBit]],\n",
    "    qbv_block: Output[QBit],\n",
    "    qbv_aux: Output[QBit],\n",
    ") -> None:\n",
    "    qbv_reg = QArray(\"qbv_reg\")\n",
    "\n",
    "    prepare_amplitudes(b.tolist(), 0, qbv_state)\n",
    "\n",
    "    allocate(1, qbv_block)\n",
    "    bind([qbv_state, qbv_block], qbv_reg)\n",
    "\n",
    "    my_qsvt_inversion(\n",
    "        phase_seq=list(phases),\n",
    "        u=lambda arg0: unitary(\n",
    "            # Here we can just use the transpose of A as is it real valued\n",
    "            elements=U_a.T.tolist(),\n",
    "            target=arg0,\n",
    "        ),\n",
    "        qbv_reg=qbv_reg,\n",
    "        qbv_aux=qbv_aux,\n",
    "    )\n",
    "\n",
    "    bind(qbv_reg, [qbv_state, qbv_block])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f0561842-db43-44d4-8a99-ae088ad082d2",
   "metadata": {},
   "source": [
    "## Synthesizing and Executing the circuit using state-vector simulator, to get $x=A^{-1}b$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "f085e5b1-03d0-4852-a715-e4ea9f85e61b",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.707049Z",
     "start_time": "2024-04-10T09:50:05.661407Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:12.294422Z",
     "iopub.status.busy": "2024-05-07T14:31:12.293437Z",
     "iopub.status.idle": "2024-05-07T14:31:12.412356Z",
     "shell.execute_reply": "2024-05-07T14:31:12.411592Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import create_model, execute, set_execution_preferences, show, synthesize\n",
    "from classiq.execution import (\n",
    "    ClassiqBackendPreferences,\n",
    "    ClassiqSimulatorBackendNames,\n",
    "    ExecutionPreferences,\n",
    ")\n",
    "\n",
    "# convert the functions to a qmod model\n",
    "qmod = create_model(main)\n",
    "\n",
    "# we will want to execute this qmod on a state-vector simulator:\n",
    "execution_preferences = ExecutionPreferences(\n",
    "    num_shots=1,\n",
    "    backend_preferences=ClassiqBackendPreferences(\n",
    "        backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR\n",
    "    ),\n",
    ")\n",
    "qmod = set_execution_preferences(qmod, execution_preferences)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b37039d0-7273-4557-b755-60094536227c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:05.707559Z",
     "start_time": "2024-04-10T09:50:05.700022Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:12.416255Z",
     "iopub.status.busy": "2024-05-07T14:31:12.415989Z",
     "iopub.status.idle": "2024-05-07T14:31:12.465014Z",
     "shell.execute_reply": "2024-05-07T14:31:12.464240Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import write_qmod\n",
    "\n",
    "write_qmod(qmod, name=\"qsvt_matrix_inversion\", decimal_precision=15)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b96713f1-e21d-48fb-b395-dd892ca4d85d",
   "metadata": {},
   "source": [
    "synthesize the model to a quantum program:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "467ef1c5-b81d-4fe6-b47f-c3f6ae91cbd3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-10T09:50:10.020658Z",
     "start_time": "2024-04-10T09:50:05.713052Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:12.469374Z",
     "iopub.status.busy": "2024-05-07T14:31:12.469062Z",
     "iopub.status.idle": "2024-05-07T14:31:27.155694Z",
     "shell.execute_reply": "2024-05-07T14:31:27.154904Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening: https://platform.classiq.io/circuit/4f5715c6-3b5e-426d-9bee-1a0705c1e032?version=0.41.0.dev39%2B79c8fd0855\n"
     ]
    }
   ],
   "source": [
    "qprog = synthesize(qmod)\n",
    "show(qprog)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2c6bdcf-12ac-4088-bc5b-291d62339458",
   "metadata": {},
   "source": [
    "Execute on the simulator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "576fe585-21e8-49cb-aa32-e3308fc763f9",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2024-04-10T09:50:10.019707Z"
    },
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:27.160529Z",
     "iopub.status.busy": "2024-05-07T14:31:27.159415Z",
     "iopub.status.idle": "2024-05-07T14:31:28.881008Z",
     "shell.execute_reply": "2024-05-07T14:31:28.880221Z"
    }
   },
   "outputs": [],
   "source": [
    "raw_results = execute(qprog).result()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53655a1e-6860-4cf1-9fb5-8d5ee6796cb5",
   "metadata": {},
   "source": [
    "## Post processing"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c33e2a62-a07c-4cd1-bfe0-ab4bff32f604",
   "metadata": {},
   "source": [
    "We will be interested in the projection of the state vector on the states where both the auxilliary qubit and the block qubit are $|0\\rangle$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "79e12764-6197-4f0d-a1c9-540794c69756",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:28.886337Z",
     "iopub.status.busy": "2024-05-07T14:31:28.885143Z",
     "iopub.status.idle": "2024-05-07T14:31:28.893066Z",
     "shell.execute_reply": "2024-05-07T14:31:28.892350Z"
    }
   },
   "outputs": [],
   "source": [
    "def parse_results(res):\n",
    "    parsed_state_vector = res[0].value.parsed_state_vector\n",
    "\n",
    "    d = {\n",
    "        parsed_state[\"qbv_state\"]: parsed_state.amplitude\n",
    "        for parsed_state in parsed_state_vector\n",
    "        if parsed_state[\"qbv_aux\"] == parsed_state[\"qbv_block\"] == 0.0\n",
    "    }\n",
    "\n",
    "    values = np.array([d[i] for i in range(len(d))])\n",
    "    global_phase = np.angle(values)[0]\n",
    "    values = np.real(values / np.exp(1j * global_phase))\n",
    "    normalization = np.linalg.norm(\n",
    "        [\n",
    "            parsed_state.amplitude\n",
    "            for parsed_state in parsed_state_vector\n",
    "            if parsed_state[\"qbv_block\"] == 0.0\n",
    "        ]\n",
    "    )\n",
    "    computed_x = values / normalization\n",
    "    return computed_x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "79a8a4bc-30ec-4867-a51f-f5681e8c436a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:28.897845Z",
     "iopub.status.busy": "2024-05-07T14:31:28.896720Z",
     "iopub.status.idle": "2024-05-07T14:31:28.904383Z",
     "shell.execute_reply": "2024-05-07T14:31:28.903750Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.30898649  0.02161539  0.14214859 -0.26100822]\n"
     ]
    }
   ],
   "source": [
    "computed_x = parse_results(raw_results)\n",
    "print(computed_x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "395a1556-bde5-442d-bb38-aa6f95934143",
   "metadata": {},
   "source": [
    "Now compare to the expected solution:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "ee3b1983-fe14-4ffe-8402-bff1c4b3ad05",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:31:28.908919Z",
     "iopub.status.busy": "2024-05-07T14:31:28.907783Z",
     "iopub.status.idle": "2024-05-07T14:31:28.920685Z",
     "shell.execute_reply": "2024-05-07T14:31:28.920069Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.29134204  0.02176207  0.13386997 -0.24527315]\n"
     ]
    }
   ],
   "source": [
    "expected_x = 1 / (2 * kappa) * (np.linalg.inv(A) @ b)\n",
    "print(expected_x)\n",
    "\n",
    "assert np.allclose(computed_x, expected_x, rtol=0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51b5574e-adb4-4467-b424-e14c0bc20b36",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "## References\n",
    "\n",
    "<a id='grand'>[1]</a>: [Martyn JM, Rossi ZM, Tan AK, Chuang IL. Grand unification of quantum algorithms. PRX Quantum. 2021 Dec 3;2(4):040203.](https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.2.040203)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
